package com.cskaoyan.javase._1interface._0introduction;

/**
 * 接着抽象类的猫狗案例:
 * 现在我们有了新需求：
 *      一部分猫和狗，经过了特殊训练，能够直立行走了。
 *      那么这群特殊的猫和狗，怎么描述它们呢？
 * 分析：
 *      1.部分猫和狗经过特殊训练，才能够直立行走。
 *      所以这个直立行走的行为不可能直接加到Cat类和Dog类中.不是所有猫狗都有这个行为。
 *      2.而特殊的猫狗仍然是猫和狗，所以它们肯定还要继承猫和狗这两个类。
 *      这时候想到的就是：重新定义两个新的猫狗类（比如超级狗和猫）继承猫狗，然后给出直立行走的方法就算完事了。
 * 这样做不是不行，需求是实现了，但还有一些小问题：
 *      1.一方面没有体现代码复用。
 *      2.更重要的是，没有体现出特殊训练的过程。
 *      假如还有一些动物也要直立行走，
 *      增加这个行为，
 *      如何体现出规范性、标准性呢？
 *      体现出它们是特殊的经过训练的动物呢？
 * 这里我们想到了抽象类，因为抽象类中抽象方法，可以强制约束子类实现它，
 * 这样就是一种标准和规范，体现了它经过了特殊训练，和之前不同了。
 * 于是我们定义抽象类，给出抽象方法，让超级猫狗类去继承这个抽象类，可行吗？
 *
 * 理想很美好，现实很骨感。显然做不到，
 * 因为Java不支持多继承。
 * 除开这点这么做也不是完美的，问题是：
 *      1.这个抽象类里面是对功能和行为的抽象，缺少属性（单独一个直立行走的行为是一个什么对象？）所以单独的行为不应该被抽象为类，不符合类的定义。
 *
 *      2.继承这个抽象类也不符合继承的"is-a"关系
 *      这里不适用于继承
 *
 * 总之,我们为了制定经过特殊训练的规范标准,使用抽象类这种数据类型,是不合适的.
 * 于是，我们就迫切需要一种全新的数据类型，这种全新的数据类型：
 *      1.不强调属性，只强调行为的抽象，"继承"它表示功能的扩展。
 *      2.在一个类继承某个类后，还能继续"继承"，不受Java单继承限制。
 *      3.没有"is-a"这种继承关系的限制。
 *      4.最好还有抽象方法。（因为它能表示规范和标准）
 *
 * 符合以上四点,Java中的数据类型,就是接口(interface)
 *
 *
 * 接口的定义:
 * 语法:
 * [访问权限修饰符] interface 接口名{}
 * 解释:
 *      1.接口的访问权限修饰符和class类一模一样
 *      2.interface和class是同种级别的数据类型
 *          都是引用数据类型
 *          它们是平行的关系
 *          class表示声明类
 *          interface表示声明接口
 *      3.接口名和类名一样,大驼峰,见名知意等等
 *
 * 接口的特点:
 *      1.接口和抽象类一样,都不能实例化,都不能创建对象.
 *      2.接口注重对行为的抽象,接口中可以定义抽象方法.
 *      3.接口的"继承"
 *      一个普通类是可以"继承"接口的
 *      称之为"实现"接口
 *      使用关键字"implements"
 *      实现接口的类,可以称之为接口的"子类"或者"实现类"
 *      接口可以称之为该类的"父接口"(其实就是父类)
 *
 *      4.一个普通类可以在继承类的同时再去实现接口
 *          但是一定要注意"先继承,再实现"
 *          普通类实现接口,也必须实现接口中的所有抽象方法
 *          实现接口中的抽象方法,也是方法的重写
 *
 *      5,接口的实现,是"多实现"
 *      一个类可以实现多个接口
 *
 * 使用接口有如下优点：
 *      1.接口不受单继承限制，这是接口非常重要的优点。
 *          一个类可以在继承某个类的同时,再去实现接口,而且可以实现多个接口
 *          这一点很重要.
 *      2.接口不是类，它和它的实现类，也不需要存在"is-a"关系，
 *          接口比抽象类的使用更加灵活。
 *          程序开发中将接口和它的实现类之间的关系，
 *              称之为"like-a"关系。只要是实现了Xxx的功能，就像Xxx。
 *          解释:
 *              比如一个箱子,一个盒子
 *              它只要实现了空调的功能(制热和制冷)
 *              它虽然不是空调,但它"像"空调
 *              这就是"like-a"的关系
 *              所以接口就表示对功能的扩展,不用想那么多,只要想扩展功能,就用接口.
 *
 *      3.接口表示一种开发标准，一种规范。
 *          表示对功能的扩展，它只关注行为，不关注属性。
 *
 * @since 11:06
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'SpecialSkill' is abstract; cannot be instantiated
        // new SpecialSkill();

        // 创建SuperDog对象,有几种方式呢? (排除Object引用接收)
        Dog d = new SuperDog();
        BaseAnimal ba = new SuperDog();
        // 类实现接口,接口就是父接口,也可以用引用指向子类对象
        SpecialSkill ss = new SuperDog();
        A a = new SuperDog();
        SuperDog sd = new SuperDog();


        // 父接口引用指向不同的实现类对象,仍然存多态现象
        SpecialSkill ss2;
        ss2 = new SuperDog();
        ss2.walkUpright();
        ss2 = new SuperCat();
        ss2.walkUpright();
    }
}

abstract class BaseAnimal {
    public abstract void shout();
}

class Cat extends BaseAnimal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends BaseAnimal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}

class SuperCat extends Cat implements SpecialSkill {
    @Override
    public void walkUpright() {
        System.out.println("我是超威蓝猫,我可以直立行走!");
    }
}

class SuperDog extends Dog implements SpecialSkill, A {
    @Override
    public void walkUpright() {
        System.out.println("我是汪汪队队长,我可以直立行走!");
    }
}

/*
    该抽象类用于制定动物经过特殊训练的标准
    通过抽象类中的抽象方法
  */
abstract class BaseSpecialSkill {
    public abstract void walkUpright();
}

// 定义接口
interface SpecialSkill {
    public abstract void walkUpright();
}

interface A {
}